//
//  TreeCache.m
//  SpaceViking
//
//  Created by gnt on 12/13/11.
//  Copyright 2011 __MyCompanyName__. All rights reserved.
//

#import "TreeCache.h"

@implementation TreeCache

+(id) cache
{
	return [[[self alloc] init] autorelease];
}

static float zMap[Const_ROADLINES];
float dx;
int ddx = 5;
float zdx = 0;

- (void) dealloc {
    [treeArray release];
    treeArray = nil;
    [troopArray release];
    troopArray = nil;
    [troopDiedArray release];
    troopDiedArray = nil;
    [radarPointArray release];
    radarPointArray = nil;
    [super dealloc];
}


- (void)addHourseStrenghtBar {
    CGSize screenSize = [[CCDirector sharedDirector] winSize];
    
    CCSprite *tileBarLeft = [[CCSprite alloc]initWithSpriteFrameName:@"blood_tile_first1.png"];
//    CCSprite *tileBarRight = [[CCSprite alloc]initWithSpriteFrameName:@"blood_tile_last1.png"];
//    CCSprite *tileBarMiddle = [[CCSprite alloc]initWithSpriteFrameName:@"blood_tile_middle1.png"];
    
    float pX = screenSize.width/4;
    float pY = screenSize.height - tileBarLeft.contentSize.height * 2;
    tileBarLeft.position = CGPointMake(pX, pY);
    [self addChild:tileBarLeft z: 107];
    
    for(int i = 0; i < 30; i++) {
        CCSprite *tileBarMiddle = [[CCSprite alloc]initWithSpriteFrameName:@"blood_tile_middle1.png"];
        pX += tileBarMiddle.contentSize.width;
        tileBarMiddle.position = CGPointMake(pX, pY);
        [self addChild:tileBarMiddle z: 107];
    }
}

-(id) init
{
	if ((self = [super init]))
	{
        Consts_PERCENT_USED = 0.6;
        Consts_Z = 1;
        CGSize screenSize = [[CCDirector sharedDirector] winSize];
        Consts_START_Z = (int) (screenSize.height * Consts_PERCENT_USED);
        Consts_Z = - (screenSize.height * (Consts_PERCENT_USED) * Consts_START_Z_SCALE 
                      + screenSize.height * (1 - Consts_PERCENT_USED) * Consts_START_Z_SCALE);
        zX = screenSize.width/2;
        numOfTrees = 0;
        //numOfTroops = 0;
        treeArray = [[NSMutableArray alloc]init];
        troopArray = [[NSMutableArray alloc]init];
        troopDiedArray = [[NSMutableArray alloc]init];
        radarPointArray = [[NSMutableArray alloc]init];
        [self calculatePseudoDepth];
        
        // Move x,y of item on Radar
        radarMoveY = Const_ZSPEED / (zMap[Const_ROADLINES-1] - zMap[0])*63.f;
//        radarMoveX = (float)ddx / (screenSize.width * 63.f * 2 / 5.f);
	}
	
    [self addHourseStrenghtBar];
    // Call game logic about every second
    [self schedule:@selector(gameLogic:) interval:0.8];
    [self schedule:@selector(update:)];
    
    return self;
}


/*
    Create radar on the Top-Right of Screen, Init "Troop Position Point" on it.
 */
- (void)addRadarItem: (TroopEntity*)troopAdd {
    CGSize screenSize = [[CCDirector sharedDirector] winSize];
    RadarItemEntity *troopPoint = [RadarItemEntity initRadarItem:@"radar_point_troop.png"];
//    float px = troopAdd.position.x / screenSize.width * 63 * 2 + (screenSize.width - 5 - 150);
    float px = (radarCharacter.contentSize.width / screenSize.width * troopAdd.position.x) 
    + radarCharacter.position.x;
//    float py = screenSize.height - 5 -12;
    float py = (radarCharacter.contentSize.height/screenSize.height * troopAdd.position.y)
    + radarCharacter.position.y + 20;

    troopPoint.currentZMapIndex = troopAdd.currentZMapIndex;
    troopPoint.position = CGPointMake(px, py);
    [radarPointArray addObject:troopPoint];
    [self addChild:troopPoint z:105];
}

- (void)updateRadarItem {
    //cach 1:
    BackgroundLayer* bg = [BackgroundLayer sharedBackgroundLayer];
    for(CCSprite *troopPoint in radarPointArray) {
//      troopPoint.position = CGPointMake(troopPoint.position.x, troopPoint.position.y - radarMoveY);
        if(bg.turn == RIGHT) {
            troopPoint.position = CGPointMake(troopPoint.position.x + radarMoveX, troopPoint.position.y - radarMoveY);
        }
        else if(bg.turn == LEFT) {
            troopPoint.position = CGPointMake(troopPoint.position.x - radarMoveX, troopPoint.position.y - radarMoveY);
        }
        else {
            troopPoint.position = CGPointMake(troopPoint.position.x, troopPoint.position.y - radarMoveY);
        }
    }
    
    //cach 2:
//    CGSize screenSize = [[CCDirector sharedDirector] winSize];    
//    for(TroopEntity *troop in troopArray) {
//        float px = (radarCharacter.contentSize.width / screenSize.width * troop.position.x) 
//        + radarCharacter.position.x;
//        float py = (radarCharacter.contentSize.height/screenSize.height * troop.position.y)
//        + radarCharacter.position.y + 20;
//        
//        troopPoint.position = CGPointMake(px, py);
//    }
}

- (void)addTreeStright {
    CCLOG(@"spawn tree");
    int typeTree = (arc4random()%3);
	TreeEntity* tree = [TreeEntity treeWithType:typeTree];
    CGSize screenSize = [[CCDirector sharedDirector] winSize];
	CGSize spriteSize = [tree contentSize];

    float yPos = screenSize.height * 0.66;
    int minX = spriteSize.width / 2;
    int maxX = screenSize.width - minX;
    int rangeX = maxX - minX;
    float xPos = (arc4random()%rangeX) + minX;
    
    [tree setUnshiftX:xPos];
    [tree setUnshiftY:yPos];
    float xRender = xPos;
    float yRender = yPos;// - spriteSize.height/2;
    
    // tinh SCALE
    tree.scale = Const_INITXSCALE;
    
    [tree setCurrentZMapIndex: Const_ROADLINES - 1];
    [tree setCurrentZ: zMap[Const_ROADLINES - 1]];
	tree.position = CGPointMake(xRender, yRender);
	
	// Finally set yourself to be visible, this also flag the tree as "in use"
	tree.visible = YES;
    tree.tag = 1;
    numOfTrees++;
    [treeArray addObject:tree];
    [self addChild:tree z:1000 - numOfTrees];
}

- (void)addTroopStright {
    CCLOG(@"spawn tree");
    int typeTroop = (arc4random()%2);
	TroopEntity* troop = [TroopEntity troopWithType:typeTroop];
    CGSize screenSize = [[CCDirector sharedDirector] winSize];
	CGSize spriteSize = [troop contentSize];

//    CCLOG(@"troop height: %f",spriteSize.height);
    float yPos = screenSize.height * 0.66;
    int minX = spriteSize.width / 2;
    int maxX = screenSize.width - minX;
    int rangeX = maxX - minX;
    float xPos = (arc4random()%rangeX) + minX;
    
    [troop setUnshiftX:xPos];
    [troop setUnshiftY:yPos];
    float xRender = xPos;
    float yRender = yPos;// - spriteSize.height;
    
    // tinh SCALE
    troop.scale = Const_INITXSCALE;
    
    [troop setCurrentZMapIndex: Const_ROADLINES - 1];
    [troop setCurrentZ: zMap[Const_ROADLINES - 1]];
	troop.position = CGPointMake(xRender, yRender);
	
	// Finally set yourself to be visible, this also flag the troop as "in use"
	troop.visible = YES;
    troop.tag = 2;
    [troopArray addObject:troop];
    [self addChild:troop];
    [self addRadarItem:troop];
}

/* 
 2 option, add tree or add troop random 
*/
- (void)addTargetStright {
    
    int randId = (int)arc4random() % 2;
    if (randId == 0) {
        [self addTroopStright];
    } else {
        [self addTreeStright];
    }
}


-(void)gameLogic:(ccTime)dt {
    [self addTargetStright];
}


-(void) update: (ccTime)delta
{
//	timeOfGame += delta;
    CGSize screenSize = [[CCDirector sharedDirector] winSize];
    BackgroundLayer* bg = [BackgroundLayer sharedBackgroundLayer];

    
    samuraiCharacter = (Samurai*) [[self parent]getChildByTag:kSamuraiSpriteTagValue];
    yCollide = samuraiCharacter.position.y;
    fromXCollide = (screenSize.width - samuraiCharacter.contentSize.width)/2;
    toXCollide = (screenSize.width + samuraiCharacter.contentSize.height)/2;
    
    radarCharacter = (CCSprite*) [[self parent]getChildByTag:kRadarSpriteTagValue];
    radarMoveX = dx / (screenSize.width/4 * 6.3f);
//    CCLOG(@"radarmoveX: %f",radarMoveX);
    
    if(bg.turn == RIGHT) {
        if (zX > screenSize.width / 2) {
            dx -= ddx;
            zdx = dx;
            zX -= ddx;
        }else {
            if (dx < screenSize.width / 2) {
                dx += ddx;
                zdx = -dx;
                zX -= ddx;
            } else {
                //previousTurn = Turn.LEFT;
            }
        }
    }else if(bg.turn == LEFT) {
        if (zX < screenSize.width / 2) {
            dx -= ddx;
            zdx = -dx;
            zX += ddx;
        } else {
            if (dx < screenSize.width / 2) {
                dx += ddx;
                zdx = dx;
                zX += ddx;
            } else {
                //previousTurn = Turn.RIGHT;
            }
        }
    }
    else {
        //currentStage.stageStright();
        //CCLOG(@"STRIGHT");
        if (dx > 0) {
            dx -= ddx;
            
            if (zX < screenSize.width/ 2) {
                zdx = -dx;
                zX += ddx;
            } else {
                zdx = dx;
                zX -= ddx;
            }
        } else {
            //previousTurn = Turn.STRIGHT;
        }
    }
    
    
    for(TreeEntity *tree in treeArray)
    {
        //TreeEntity* tree = (TreeEntity*)[treeBatchNode getChildByTag:j];
        float origX = [tree unshiftX];
        float origY = [tree unshiftY];
        // decrease z speed
        [tree setCurrentZ: [tree currentZ] - Const_ZSPEED];
        
        if (tree.currentZMapIndex - 1 >= 0 && tree.currentZ < zMap[(tree.currentZMapIndex - 1)]) {
            int step = 2;
            for (step = 2; step < Const_ROADLINES; step++) {
                if (tree.currentZMapIndex - step < 0
                    || tree.currentZ > zMap[(tree.currentZMapIndex - step)]) {
                    break;
                }
            }
            step = step - 1;
            float increaseY =  Consts_INCREASE_Y *step;
            tree.currentZMapIndex -= step;
            float newY = origY - increaseY;
            float scaleLevel = (Consts_Z - (origY + increaseY)) / (Consts_Z - origY);
            float newX = (origX - zX)*scaleLevel + zX;
            
            //tree scale, viet 2 cach:
//            tree.scale = (tree.scale * (1.025f + increaseY / (origY + Consts_Z)));
            tree.scale =(float)(Const_INITXSCALE - 4)/Const_ROADLINES * tree.currentZMapIndex + 4;
            float lineScale = (1 - (float) tree.currentZMapIndex / Const_ROADLINES);
            
            [tree setUnshiftX:newX];
            [tree setUnshiftY:newY];
            newX -= zdx*lineScale;
            float xRender = newX;
            float yRender = newY;// - tree.contentSize.height/2;
//            float xRender = newX - (tree.contentSize.width * tree.scale)/2;
//            float yRender = newY - (tree.contentSize.height * tree.scale);
            tree.position = CGPointMake(xRender, yRender);
        }
    }
    
    //update for troop
//    TroopEntity* troop;
//    CCARRAY_FOREACH([troopBatchNode children], troop)
    for(TroopEntity *troop in troopArray)
    {
        if(!troop.hit) {
            float origX = [troop unshiftX];
            float origY = [troop unshiftY];
            [troop setCurrentZ: [troop currentZ] - Const_ZSPEED];
            
            if (troop.currentZMapIndex - 1 >= 0 && troop.currentZ < zMap[(troop.currentZMapIndex - 1)]) {
                int step = 2;
                for (step = 2; step < Const_ROADLINES; step++) {
                    if (troop.currentZMapIndex - step < 0
                        || troop.currentZ > zMap[(troop.currentZMapIndex - step)]) {
                        break;
                    }
                }
                step = step - 1;
                float increaseY =  Consts_INCREASE_Y *step;
                troop.currentZMapIndex -= step;
                float newY = origY - increaseY;
                float scaleLevel = (Consts_Z - (origY + increaseY)) / (Consts_Z - origY);
                float newX = (origX - zX)*scaleLevel + zX;
                
                troop.scale = (troop.scale * (1.025f + increaseY / (origY + Consts_Z)));
                float lineScale = (1 - (float) troop.currentZMapIndex / (float) Const_ROADLINES);
                
                [troop setUnshiftX:newX];
                [troop setUnshiftY:newY];
                newX -= zdx*lineScale;
                float xRender = newX;
                float yRender = newY;// - troop.contentSize.height;
                troop.position = CGPointMake(xRender, yRender);            
            }
        }
        else {
            float origX = [troop unshiftX];
            float origY = [troop unshiftY];
            float newX = origX;
            float newY = origY+50;
            [troop setUnshiftX:newX];
            [troop setUnshiftY:newY];  
            troop.position = CGPointMake(newX, newY);
        }
    }
    
    
    //check collision 
    for(TroopEntity *troop in troopArray) {
        if(troop.position.y <= yCollide) {
//            if (troop.position.x + troop.contentSize.width * troop.scaleX / 2.f > fromXCollide && troop.position.x + troop.contentSize.width * troop.scaleX / 2.f < toXCollide) {
            if (([troop unshiftX] > fromXCollide && [troop unshiftX] < toXCollide) 
                || (([troop unshiftX] + troop.contentSize.width*troop.scaleX/2.f) > fromXCollide && ([troop unshiftX] + troop.contentSize.width*troop.scaleX/2.f < toXCollide))
                || (([troop unshiftX] - troop.contentSize.width*troop.scaleX/2.f) > fromXCollide && ([troop unshiftX] + troop.contentSize.width*troop.scaleX/2.f < toXCollide))
                ) {
                troop.hit = YES;
                samuraiCharacter.deadTroop += 1;
//                id moveAction = [CCMoveTo actionWithDuration:5.0f
//                                                    position:ccp(troop.position.x, troop.position.y+100)];
//                [troop runAction:moveAction];
            }
            break;
        }
    }
    
    
    [self checkOutScreen];
    [self updateRadarItem];
}

-(void) calculatePseudoDepth {
    int loop = Const_ROADLINES;
    for (int i = 0; i <= loop; i++) {
        zMap[i] = (1 / ((float) i - Const_ROADLINES - 15));
    }
    playerZ =(float) 110 / zMap[8];
    for (int i = 0; i <= loop; i++) {
        zMap[i] *= playerZ;
        CCLOG(@"zMap[%d]: %f",i,zMap[i]);
    }
}


- (BOOL)checkInCircle: (RadarItemEntity*)radarPoint {
    float x = radarCharacter.position.x + radarCharacter.contentSize.width/2;
    float y = radarCharacter.position.y + radarCharacter.contentSize.height/2;
    CGPoint center = CGPointMake(x,y);
    CGPoint checkPoint = CGPointMake(radarPoint.position.x, radarPoint.position.y);
    float r = 140/2;
    
    BOOL isInside = ( ccpDistance(center, checkPoint) < r );
    return isInside;
}

-(void) checkOutScreen
{
//    CGSize screenSize = [[CCDirector sharedDirector] winSize];
    
    NSMutableArray *treeOutScreen = [[NSMutableArray alloc]init];
    for(TreeEntity *tree in treeArray) {
        if(tree.currentZMapIndex <= 0) {
            [treeOutScreen addObject:tree];
        }
    }
    for(TreeEntity *tree in treeOutScreen) {
        [treeArray removeObject:tree];
        [self removeChild:tree cleanup:YES];	
    }
    
    
    NSMutableArray *troopOutScreen = [[NSMutableArray alloc]init];
    for(TroopEntity *troop in troopArray) {
        if(troop.currentZMapIndex <= 0) {
            [troopOutScreen addObject:troop];
        }
    }
    for(TroopEntity *troop in troopOutScreen) {
        [troopArray removeObject:troop];
        [self removeChild:troop cleanup:YES];	
    }
    
    NSMutableArray *radarItemOutScreen = [[NSMutableArray alloc]init];
    for(RadarItemEntity *radarItem in radarPointArray) {
        if(![self checkInCircle:radarItem]) {
           [radarItemOutScreen addObject:radarItem];
        }
    }
    for(RadarItemEntity *radarItem in radarItemOutScreen) {
        [radarPointArray removeObject:radarItem];
        [self removeChild:radarItem cleanup:YES];
    }
    
    [treeOutScreen release];
    [troopOutScreen release];
    [radarItemOutScreen release];
}


@end